/*
https://yq.aliyun.com/ziliao/72587

获取农历

农历月的天数是一个变数，有时是 29 天，有时是 30 天。

农历每月的第一天是月亮全黑的日子。

农历年由 24 个节气来确定，节气则由太阳的角度来确定。农历的第一个节气叫 雨水，定在太阳的角度为 330 度的日子。其余的 23 个节气分别定在太阳的角度 每变化 15 度的日子。下面的表格列出了 24 个节气的名称和定义：

命称    角度    公历日期      周期

立春     315     2月 4日

雨水     330     2月19日    29.8天

惊蛰     345     3月 6日

春分       0     3月21日    30.2天

清明      15     4月 5日

谷雨      30     4月20日    30.7天

立夏      45     5月 6日

夏满      60     5月21日    31.2天

芒种      75     6月 6日

夏至      90     6月22日    31.4天

小暑     105     7月 7日

大暑     120     7月23日    31.4天

立秋     135     8月 8日

处暑     150     8月23日    31.1天

白露     165     9月 8日

秋分     180     9月23日    30.7天

寒露     195    10月 8日

霜降     210    10月24日    30.1天

立冬     225    11月 8日

小雪     240    11月22日    29.7天

大雪     255    12月 7日

冬至     270    12月22日    29.5天

小寒     285     1月 6日

大寒     300     1月20日    29.5天

24 个节气中有 12 个是主节气：雨水，春分，谷雨，夏满，夏至，大暑，处暑， 秋分，霜降，小雪，冬至，大寒。

农历年跟天文年相差较大。农历常年有十二个农历月，有 353，354，或者 355 天，比天文年少大约 11 天。为了跟天文年同步，每隔三个农历常年左右，必需设 一闰年。闰年有十三个月，添加的这个月叫闰月。

农历十二个月的名称分别为：正月，二月，三月，四月，五月，六月，七月，八 月，九月，十月，冬月，腊月。

农历闰年闰月的确定比较难，闰月农历算法有两条：

•一：冬至必须落在农历冬月。如果落不上，腊月之前就要添上一个月，成为闰 年。
•二：如果是闰年，冬月后边第一个不含主节气的月份定为闰月。闰月使用前一 月份的名称。
农历年以 60 年为一周期，每年的名称由 10 个天干的一个字和 12 个地支的一 个字排列而成。

10 天干为：

•甲，乙，丙，丁，戊，己，庚，辛，壬，癸。
12 地支 为：

•子，丑，寅，卯，辰，巳，午，未，申，酉，戌，亥。
•12 地支有 12 动物生肖 与其对应：
鼠，牛，虎，兔，龙，蛇，马，羊，猴，鸡，狗，猪。
跟据历史记载，农历年已经经过了 78 个周期。今年，公历2010 年，是第 79 个周期的第 28 年，也就是农历第 4707 年

*/

export default {

    lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
        0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,
        0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
        0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
        0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,
        0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
        0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,
        0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
        0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,
        0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
        0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,
        0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,
        0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,
        0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,
        0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0],

//==== 传回农历 y年的总天数
    lyeardays(y) {
        let i, sum = 348;
        for (i = 0x8000; i > 0x8; i >>= 1) sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0
        return (sum + this.leapdays(y))
    },
//==== 传回农历 y年闰月的天数
    leapdays(y) {
        if (this.leapmonth(y)) {
            return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29);
        } else {
            return (0);
        }
    },
//==== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
    leapmonth(y) {
        return (this.lunarInfo[y - 1900] & 0xf)
    },
//====================================== 传回农历 y年m月的总天数
    monthdays(y, m) {
        return ( (this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29 )
    },
//==== 算出农历, 传入日期物件, 传回农历日期物件
//     该物件属性有 .year .month .day .isleap .yearcyl .daycyl .moncyl
    lunar(objdate) {
        let i, leap = 0, temp = 0;
        let basedate = new Date(1900, 0, 31);
        let offset = (objdate - basedate) / 86400000;
        objdate.daycyl = offset + 40;
        objdate.moncyl = 14;
        for (i = 1900; i < 2050 && offset > 0; i++) {
            temp = this.lyeardays(i);
            offset -= temp;
            objdate.moncyl += 12;
        }
        if (offset < 0) {
            offset += temp;
            i--;
            objdate.moncyl -= 12;
        }
        objdate.year = i;
        objdate.yearcyl = i - 1864;
        leap = this.leapmonth(i); //闰哪个月
        objdate.isleap = false;
        for (i = 1; i < 13 && offset > 0; i++) {
//闰月
            if (leap > 0 && i === (leap + 1) && objdate.isleap === false) {
                --i;
                objdate.isleap = true;
                temp = this.leapdays(objdate.year);
            }
            else {
                temp = this.monthdays(objdate.year, i);
            }
//解除闰月
            if (objdate.isleap === true && i === (leap + 1)) objdate.isleap = false;
            offset -= temp;
            if (objdate.isleap === false) objdate.moncyl++
        }
        if (offset === 0 && leap > 0 && i === leap + 1)
            if (objdate.isleap) {
                objdate.isleap = false;
            }
            else {
                objdate.isleap = true;
                --i;
                --objdate.moncyl;
            }
        if (offset < 0) {
            offset += temp;
            --i;
            --objdate.moncyl;
        }
        objdate.month = i;
        objdate.day = offset + 1;

        return objdate;
    },
    cday(m, d) {
        let nstr1 = ['日', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
        let nstr2 = ['初', '十', '廿', '卅', '　'];
        let s;
        if (m > 10) {
            s = '十' + nstr1[m - 10]
        } else {
            s = nstr1[m]
        }
        s += '月';
        if (s === "十二月") s = "腊月";
        if (s === "一月") s = "正月";
        switch (d) {
            case 10:
                s += '初十';
                break;
            case 20:
                s += '二十';
                break;
            case 30:
                s += '三十';
                break;
            default:
                s += nstr2[Math.floor(d / 10)];
                s += nstr1[d % 10];
        }
        return (s);
    },
    solar(date) {
        let sdobj = new Date(date.getFullYear(), date.getMonth(), date.getDate());
        let ldobj = this.lunar(sdobj);
        return this.cday(ldobj.month, ldobj.day);
    }
}